package com.bestcem.xm.user.controller;

import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.lang.ObjectId;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.xm.common.core.constant.RegTypes;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.domain.web.XmResultJson;
import com.bestcem.xm.common.core.enums.ReqErrorCodeEnum;
import com.bestcem.xm.common.core.enums.ResourceErrorCodeEnum;
import com.bestcem.xm.common.core.exception.BusinessException;
import com.bestcem.xm.component.security.annotation.AuthIgnore;
import com.bestcem.xm.component.security.annotation.XmAuth;
import com.bestcem.xm.component.security.context.SecurityContextHolder;
import com.bestcem.xm.component.security.dto.TokenDTO;
import com.bestcem.xm.user.annotations.CheckGroupLock;
import com.bestcem.xm.user.config.mvc.ParameterConvert;
import com.bestcem.xm.user.controller.vo.PageResponseVO;
import com.bestcem.xm.user.controller.vo.group.*;
import com.bestcem.xm.user.controller.vo.group.request.UserGroupAdminVO;
import com.bestcem.xm.user.controller.vo.group.request.UserGroupCreateVO;
import com.bestcem.xm.user.controller.vo.group.request.UserGroupLayeredVO;
import com.bestcem.xm.user.enums.BooleanStatusEnum;
import com.bestcem.xm.user.enums.GroupImportRecordTypeEnum;
import com.bestcem.xm.user.enums.UserEnum;
import com.bestcem.xm.user.service.*;
import com.bestcem.xm.user.service.dto.PageResponseDTO;
import com.bestcem.xm.user.service.dto.group.*;
import com.bestcem.xm.user.service.dto.user.UserDTO;
import com.bestcem.xm.user.service.init.UserInitService;
import com.bestcem.xm.user.util.convert.UserGroupConvert;
import com.bestcem.xm.user.util.convert.UserGroupExportRecordConvert;
import com.bestcem.xm.user.util.convert.UserGroupImportRecordConvert;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 用户组服务接口提供
 *
 * @author qiongyu.cui <qiongyu.cui@idiaoyan.com>
 * @version v1.0
 * @date 2021/12/29 11:01
 */
@RestController
@Slf4j
@RequestMapping(value = "/user/groups")
public class UserGroupController {

    @Resource
    private UserGroupService userGroupService;

    @Resource
    private UserGroupConvert userGroupConvert;

    @Resource
    private UserGroupImportService userGroupImportService;

    @Resource
    private UserGroupBusinessService userGroupBusinessService;

    @Resource
    private UserGroupExportRecordService userGroupExportRecordService;

    @Resource
    private UserGroupImportRecordService userGroupImportRecordService;

    @Resource
    private UserGroupExportRecordConvert userGroupExportRecordConvert;

    @Resource
    private UserGroupImportRecordConvert userGroupImportRecordConvert;

    @Resource
    private UserService userService;

    @Resource
    private UserInitService userInitService;

    @AuthIgnore
    @GetMapping("/seq")
    public String seqSynchronize() {
        userInitService.seqSynchronize();
        return "success";
    }

    /**
     * 层级组织分层分页查询
     * 一次加载指定父组织的下一层子组织
     */
    @XmAuth
    @PostMapping(value = "/layered")
    public XmResultJson<Object> layered(@Valid @RequestBody @ParameterConvert UserGroupLayeredVO userGroupLayeredVO) {
        TokenDTO currentToken = SecurityContextHolder.getToken();

        // 分页分层查询
        ServiceResult<PageResponseDTO<UserGroupDTO>> result = userGroupService.layeredPage(userGroupLayeredVO.getParentGroupId(), currentToken.getOrgId(), currentToken.getUserId(),
                currentToken.isAdmin(), userGroupLayeredVO.getPage().getPage(), userGroupLayeredVO.getPage().getSize());
        if (result.isSuccess() && Objects.nonNull(result.getData())) {
            PageResponseDTO<UserGroupDTO> data = result.getData();
            PageResponseVO<UserGroupInfoVO> res = new PageResponseVO<>();
            res.setRows(userGroupConvert.dtosToInfoVos(data.getRows()));
            res.setTotal(Objects.isNull(data.getTotal()) ? 0 : data.getTotal());
            return XmResultJson.success(res);
        }
        if (StringUtils.isNotBlank(result.getErrorCode())) {
            // 解决类型转换报错
            int errorCode = Integer.parseInt(result.getErrorCode());
            return XmResultJson.fail(result.getErrorData(), errorCode, result.getMsg());
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 一次性加载所有组织，并拼装成树结构
     *
     * @param all true则加载本租户的所有有效组织，false则只加载用户自己挂在的组织节点及其上下级
     */
    @XmAuth
    @GetMapping(value = "/tree")
    public XmResultJson<Object> tree(@RequestParam(required = false, defaultValue = "false") boolean all) {
        TokenDTO currentToken = SecurityContextHolder.getToken();

        // 分页分层查询
        ServiceResult<GroupTreeDTO> result = userGroupService.getGroupTree(currentToken.getOrgId(), currentToken.getUserId(), currentToken.isAdmin(), all);
        if (result.isSuccess()) {
            return XmResultJson.success(result.getData());
        }
        if (StringUtils.isNotBlank(result.getErrorCode())) {
            // 解决类型转换报错
            int errorCode = Integer.parseInt(result.getErrorCode());
            return XmResultJson.fail(result.getErrorData(), errorCode, result.getMsg());
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 根据组织id查询本身以及所有父组织信息
     *
     * @param groupId 组织id
     * @return com.bestcem.xm.util.XmResultJson<com.bestcem.xm.user.group.controller.vo.group.UserGroupInfoVO>
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/02/08 10:13
     */
    @GetMapping(value = "/{group_id}/upper")
    public XmResultJson<UserGroupInfoVO> getUserGroupUpper(@Valid @PathVariable("group_id") String groupId) {
        if (!ObjectId.isValid(groupId)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_FORMAT, "组织id为空或格式不正确");
        }
        TokenDTO currentToken = SecurityContextHolder.getToken();

        // 根据组织id查询本身以及所有父组织信息
        ServiceResult<List<UserGroupDTO>> result = userGroupService.getUserGroupUpper(groupId, currentToken.getUserId(), currentToken.isAdmin());
        if (result.isSuccess()) {
            // 转换成树结构
            Map<String, UserGroupDTO> map = result.getData().stream().collect(Collectors.toMap(UserGroupDTO::getGroupId, c -> c, (c1, c2) -> c2));
            UserGroupDTO userGroupDTO = result.getData().stream().filter(r -> r.getGroupId().equals(groupId)).findFirst().orElse(null);
            if (Objects.isNull(userGroupDTO)) {
                return XmResultJson.success();
            }
            // 定义返回值
            UserGroupInfoVO res = userGroupConvert.dtoToInfoVo(userGroupDTO);
            while (StringUtils.isNotBlank(res.getGroupParentId())) {
                String groupParentId = res.getGroupParentId();
                UserGroupInfoVO userGroupInfoVoTemp = userGroupConvert.dtoToInfoVo(map.get(groupParentId));
                userGroupInfoVoTemp.setChildren(Lists.newArrayList(res));
                res = userGroupInfoVoTemp;
            }
            return XmResultJson.success(res);
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 组织失效
     *
     * @param groupId 组织id
     * @param version 组织当前版本号
     * @return com.bestcem.xm.util.XmResultJson<com.bestcem.xm.user.group.controller.vo.group.VersionVO>
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2021/12/30 13:59
     */
    @CheckGroupLock
    @DeleteMapping(value = "/invalid")
    public XmResultJson<VersionVO> invalidUserGroup(@RequestParam(name = "group_id") String groupId,
                                                    @RequestParam(name = "version") Integer version) {
        TokenDTO currentToken = SecurityContextHolder.getToken();
        // 参数校验
        if (!ObjectId.isValid(groupId)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_LOST, "groupId为空或格式不正确");
        }
        if (Objects.isNull(version)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_LOST, "version不能为空");
        }
        // 用户组失效
        ServiceResult<Integer> result = userGroupService.invalidUserGroup(currentToken.getOrgId(), groupId, version, currentToken.getUserId());
        if (result.isSuccess()) {
            return XmResultJson.success(new VersionVO(result.getData()));
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 查询指定状态下的用户组列表
     *
     * @param requestVO 查询参数
     * @return com.bestcem.xm.util.XmResultJson<java.util.List < com.bestcem.xm.user.group.controller.vo.GroupListVO>>
     * @author jishuo.yan <jishuo.yan@idiaoyan.com>
     * @date 2022/02/08 20:38
     */
    @PostMapping(value = "/list")
    public XmResultJson<PageResponseVO<UserGroupsVO>> listUserGroups(@RequestBody @Valid GroupsListRequestVO requestVO) {
        TokenDTO currentToken = SecurityContextHolder.getToken();
        String orgId = currentToken.getOrgId();
        GroupsListRequestDTO dto = userGroupConvert.groupListRequestVoToGroupListRequestDto(requestVO);
        ServiceResult<PageResponseDTO<UserGroupResumeDTO>> result = userGroupService.listPages(dto, orgId, currentToken.getUserId(), currentToken.isAdmin(), requestVO.getPage().getPage(), requestVO.getPage().getSize());
        if (result.isSuccess() && Objects.nonNull(result.getData())) {
            PageResponseDTO<UserGroupResumeDTO> data = result.getData();
            PageResponseVO<UserGroupsVO> res = new PageResponseVO<>();
            res.setRows(userGroupConvert.resumeDtosToResumeVos(data.getRows()));
            res.setTotal(Objects.isNull(data.getTotal()) ? 0 : data.getTotal());
            return XmResultJson.success(res);
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());

    }

    /**
     * 下载层级组织文件
     *
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2021/12/30 10:50
     */
    @GetMapping(value = "/download")
    public void downloadUserGroup(HttpServletResponse response) {
        // 下载
        ServiceResult<String> serviceResult = userGroupImportService.downloadUserGroup(SecurityContextHolder.getToken(), response);
        // 下载成功
        /*if (serviceResult.isSuccess()) {
            return XmResultJson.success(serviceResult.getData());
        }*/
        // 下载失败
        if (!serviceResult.isSuccess()) {
            throw new BusinessException(serviceResult.getErrorCode(), serviceResult.getMsg());
        }
    }

    @GetMapping(value = "/upload/")
    public XmResultJson<String> checkUploadLevel() {
        // 获取用户token信息, 校验并设置参数
        TokenDTO tokenDTO = SecurityContextHolder.getToken();
        ServiceResult<?> result = userGroupImportService.checkUploadLevel(tokenDTO);
        if (result.isSuccess()) {
            return XmResultJson.success();
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 上传层级组织文件
     *
     * @param excel excel文件对象
     * @return
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/2/8 11:30
     */
    @CheckGroupLock
    @PostMapping(value = "/upload")
    public XmResultJson<String> uploadUserGroup(MultipartFile excel) {
        // 获取用户token信息, 校验并设置参数
        TokenDTO tokenDTO = SecurityContextHolder.getToken();
        // 上传层级组织文件
        ServiceResult<String> serviceResult = userGroupImportService.uploadUserGroup(excel, tokenDTO);
        // 上传成功
        if (serviceResult.isSuccess()) {
            return XmResultJson.success(serviceResult.getData());
        }
        // 上传失败
        return XmResultJson.fail(Integer.parseInt(serviceResult.getErrorCode()), serviceResult.getMsg());
    }

    /**
     * 恢复失效组织
     *
     * @param userGroupResumeVO 组织失效vo
     * @param groupId           组织id
     * @return
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/1/29 10:30
     */
    @CheckGroupLock
    @PutMapping(value = "/{groupId}/resume")
    public XmResultJson<GroupInfoVO> resumeUserGroup(@RequestBody @Valid @ParameterConvert UserGroupResumeVO userGroupResumeVO,
                                                     @PathVariable("groupId") String groupId) {
        // 获取用户token信息, 校验并设置参数
        TokenDTO tokenDTO = SecurityContextHolder.getToken();
        userGroupResumeVO.setOrgId(tokenDTO.getOrgId());
        userGroupResumeVO.setOperatorId(tokenDTO.getUserId());

        if (!ObjectId.isValid(groupId)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_FORMAT);
        }
        userGroupResumeVO.setGroupId(groupId);

        // 恢复失效组织
        ServiceResult<GroupInfoDTO> serviceResult = userGroupService.resumeUserGroup(userGroupConvert.resumeVoToDto(userGroupResumeVO));
        if (!serviceResult.isSuccess()) {
            return XmResultJson.fail(userGroupConvert.infoDto2InfoVo(serviceResult.getData()),
                    Integer.valueOf(serviceResult.getErrorCode()), serviceResult.getMsg());
        }

        return XmResultJson.success();
    }

    /**
     * 请求系统自动生成组织编码
     *
     * @return com.bestcem.xm.util.XmResultJson<java.lang.String>
     * @author panyun <yun.pan@idiaoyan.com>
     * @date 2022/2/8 10:22
     */
    @GetMapping("/code/create")
    public XmResultJson<String> generateGroupCode() {
        ServiceResult<String> serviceResult = userGroupService.generateGroupCode();
        return XmResultJson.success(serviceResult.getData());
    }

    /**
     * 添加子组织
     *
     * @return com.bestcem.xm.util.XmResultJson<java.lang.Object>
     * @author panyun <yun.pan@idiaoyan.com>
     * @date 2022/2/8 16:13
     */
    @CheckGroupLock
    @PostMapping("/create")
    public XmResultJson<CreateGroupResponseVO> createSubGroup(@Valid @RequestBody UserGroupCreateVO createVO) {
        // 参数格式校验
        boolean pattern1 = Pattern.matches(RegTypes.GROUP_CODE, createVO.getGroupCode());
        boolean pattern2 = Pattern.matches(RegTypes.AUTO_CODE, createVO.getGroupCode());

        if (!pattern1 && !pattern2) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_FORMAT, "组织编码格式错误");
        }

        // 添加子组织
        TokenDTO currentToken = SecurityContextHolder.getToken();
        ServiceResult<CreateGroupResponseVO> serviceResult = userGroupService.createSubGroup(userGroupConvert.createVoToDto(createVO), currentToken);
        if (serviceResult.isSuccess()) {
            return XmResultJson.success(serviceResult.getData());
        } else {
            return XmResultJson.fail(serviceResult.getErrorData(), serviceResult.getMsg());
        }
    }

    /**
     * 设置组织负责人
     *
     * @param adminInfo 管理员信息
     * @return com.bestcem.xm.util.XmResultJson<java.lang.Object>
     * @author panyun <yun.pan@idiaoyan.com>
     * @date 2022/2/10 17:39
     */
    @CheckGroupLock
    @PostMapping({"/setAdminId", "/set_admin_id"})
    public XmResultJson<Object> setAdminId(@RequestBody @Validated UserGroupAdminVO adminInfo) {
        if (StringUtils.isBlank(adminInfo.getUserId())) {
            return XmResultJson.success();
        }
        // 通过userId判断是否是该租户下已激活的账号
        ServiceResult<UserDTO> userDTOServiceResult = userService.selectById(adminInfo.getUserId());
        if (Objects.isNull(userDTOServiceResult.getData()) ||
                BooleanStatusEnum.NO.getStatus().equals(userDTOServiceResult.getData().getStatus())) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_RANGE, "当前用户不是已激活账号");
        }

        TokenDTO currentToken = SecurityContextHolder.getToken();
        UserGroupDTO dto = new UserGroupDTO();
        dto.setAdminId(adminInfo.getUserId());
        dto.setGroupId(adminInfo.getGroupId());
        dto.setOperatorId(currentToken.getUserId());
        ServiceResult<Integer> serviceResult = userGroupService.setAdminId(dto);
        if (!serviceResult.isSuccess()) {
            return XmResultJson.fail(Integer.valueOf(serviceResult.getErrorCode()), serviceResult.getMsg());
        }
        return XmResultJson.success();
    }


    /**
     * 编辑组织/重命名
     *
     * @param groupVO 编辑组织参数
     * @return com.bestcem.xm.util.XmResultJson<java.lang.Object>
     * @author Linzhijian <zhijian.lin@idiaoyan.com>
     * @date 2022/04/02 15:15
     */
    @CheckGroupLock
    @PutMapping("/update")
    public XmResultJson<Integer> updateSubGroup(@RequestBody @Validated UpdateUserGroupVO groupVO) {
        // 参数校验
        if (!ObjectId.isValid(groupVO.getGroupId())) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_LOST, "groupId为空或格式不正确");
        }
        String userId = SecurityContextHolder.getToken().getUserId();
        UpdateUserGroupDTO updateUserGroupDTO = userGroupConvert.updateGroupVO2Dto(groupVO);
        updateUserGroupDTO.setOperatorId(userId);
        updateUserGroupDTO.setOrgId(SecurityContextHolder.getToken().getOrgId());
        ServiceResult<Integer> result = userGroupService.updateUserGroup(updateUserGroupDTO);
        if (result.isSuccess()) {
            return XmResultJson.success(result.getData());
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 移动组织
     *
     * @param groupVO 移动组织参数
     * @return com.bestcem.xm.util.XmResultJson<java.lang.Object>
     * @author Linzhijian <zhijian.lin@idiaoyan.com>
     * @date 2022/04/02 15:16
     */
    @CheckGroupLock
    @PutMapping("/move")
    public XmResultJson<Integer> moveUserGroup(@RequestBody @Validated MoveUserGroupVO groupVO) {
        ServiceResult<Integer> result = userGroupService.moveUserGroup(userGroupConvert.moveGroupVO2Dto(groupVO));
        if (result.isSuccess()) {
            return XmResultJson.success(result.getData());
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 查询当前租户组织层级是否可编辑
     *
     * @return ture/false
     * @author jishuo.yan <jishuo.yan@idiaoyan.com>
     * @date 2022/02/08 11:00
     */
    @GetMapping("/lock")
    public XmResultJson<Boolean> getLock() {
        String orgId = SecurityContextHolder.getToken().getOrgId();
        //根据org_id查询redis的组织层级锁是否存在
        ServiceResult<Boolean> result = userGroupBusinessService.getLock(orgId);
        if (result.isSuccess()) {
            return XmResultJson.success(!result.getData());
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 导入组织记录分页列表
     *
     * @param currentPage 当前页
     * @param pageSize    页条数
     * @return XmViewResultJson<PageVO < UserGroupExportRecordVO>>
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/4/20 15:28
     */
    @GetMapping("/upload/records")
    public XmResultJson<PageResponseVO<UserGroupImportRecordVO>> listGroupImportRecords(@RequestParam("page") Integer currentPage,
                                                                                        @RequestParam("size") Integer pageSize) {
        // 设置查询参数
        TokenDTO token = SecurityContextHolder.getToken();
        UserGroupImportRecordDTO exportRecordDTO = new UserGroupImportRecordDTO();
        exportRecordDTO.setOrgId(token.getOrgId());
        exportRecordDTO.setCreatorId(token.getUserId());
        exportRecordDTO.setType(GroupImportRecordTypeEnum.MANAGER.getType());
        // 系统管理员与高级管理员不限制查看日志的数据权限
        if ((token.getIsSenior() != null && UserEnum.USER_YES.getFlag().equals(token.getIsSenior()))
                || (token.getSuperRole() != null && UserEnum.USER_YES.getFlag().equals(token.getSuperRole()))) {
            exportRecordDTO.setCreatorId(null);
        }
        ServiceResult<PageResponseDTO<UserGroupImportRecordDTO>> result = userGroupImportRecordService.listByPage(exportRecordDTO, currentPage, pageSize);
        if (result.isSuccess() && result.getData() != null) {
            PageResponseDTO<UserGroupImportRecordDTO> data = result.getData();
            PageResponseVO<UserGroupImportRecordVO> pageVO = new PageResponseVO<>();
            pageVO.setRows(userGroupImportRecordConvert.dtos2Vos(data.getRows()));
            pageVO.setTotal(data.getTotal());
            return XmResultJson.success(pageVO);
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 查询导入组织记录
     *
     * @param userGroupImportRecordVO
     * @return XmResultJson<UserGroupImportRecordVO>
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/7/12 16:08
     */
    @GetMapping("/upload/record")
    public XmResultJson<UserGroupImportRecordVO> getGroupImportRecord(@ParameterConvert UserGroupImportRecordVO userGroupImportRecordVO) {
        // 校验参数
        if (!ObjectId.isValid(userGroupImportRecordVO.getImportId())) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_FORMAT, "import_id format error");
        }
        // 设置查询参数
        TokenDTO token = SecurityContextHolder.getToken();
        UserGroupImportRecordDTO exportRecordDTO = new UserGroupImportRecordDTO();
        exportRecordDTO.setOrgId(token.getOrgId());
        exportRecordDTO.setCreatorId(token.getUserId());
        exportRecordDTO.setType(GroupImportRecordTypeEnum.MANAGER.getType());
        exportRecordDTO.setImportId(userGroupImportRecordVO.getImportId());
        // 系统管理员与高级管理员不限制查看日志的数据权限
        if ((token.getIsSenior() != null && UserEnum.USER_YES.getFlag().equals(token.getIsSenior()))
                || (token.getSuperRole() != null && UserEnum.USER_YES.getFlag().equals(token.getSuperRole()))) {
            exportRecordDTO.setCreatorId(null);
        }
        // 查询导入组织记录
        ServiceResult<List<UserGroupImportRecordDTO>> result = userGroupImportRecordService.findByCondition(exportRecordDTO);
        // 设置返回值
        if (result.isSuccess()) {
            if (CollectionUtils.isEmpty(result.getData())) {
                return XmResultJson.fail(ResourceErrorCodeEnum.NOT_FOUND, "import_id not found");
            }
            return XmResultJson.success(userGroupImportRecordConvert.dto2Vo(result.getData().get(0)));
        }

        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 导出组织记录分页列表
     *
     * @param currentPage 当前页
     * @param pageSize    页条数
     * @return XmViewResultJson<PageVO < UserGroupExportRecordVO>>
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/4/20 15:28
     */
    @GetMapping("/download/records")
    public XmResultJson<PageResponseVO<UserGroupExportRecordVO>> listGroupExportRecords(@RequestParam("page") Integer currentPage,
                                                                                        @RequestParam("size") Integer pageSize) {
        // 设置查询参数
        TokenDTO token = SecurityContextHolder.getToken();
        UserGroupExportRecordDTO exportRecordDTO = new UserGroupExportRecordDTO();
        exportRecordDTO.setOrgId(token.getOrgId());
        exportRecordDTO.setCreatorId(token.getUserId());
        // 系统管理员与高级管理员不限制查看日志的数据权限
        if ((token.getIsSenior() != null && UserEnum.USER_YES.getFlag().equals(token.getIsSenior()))
                || (token.getSuperRole() != null && UserEnum.USER_YES.getFlag().equals(token.getSuperRole()))) {
            exportRecordDTO.setCreatorId(null);
        }
        ServiceResult<PageResponseDTO<UserGroupExportRecordDTO>> result = userGroupExportRecordService.listByPage(exportRecordDTO, currentPage, pageSize);
        if (result.isSuccess() && result.getData() != null) {
            PageResponseDTO<UserGroupExportRecordDTO> data = result.getData();
            PageResponseVO<UserGroupExportRecordVO> pageVO = new PageResponseVO<>();
            pageVO.setRows(userGroupExportRecordConvert.dtos2Vos(data.getRows()));
            pageVO.setTotal(data.getTotal());
            return XmResultJson.success(pageVO);
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 查询导出组织记录
     *
     * @param userGroupExportRecordVO
     * @return XmResultJson<UserGroupExportRecordVO>
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/7/12 16:08
     */
    @GetMapping("/download/record")
    public XmResultJson<UserGroupExportRecordVO> getGroupImportRecord(@ParameterConvert UserGroupExportRecordVO userGroupExportRecordVO) {
        // 校验参数
        if (!ObjectId.isValid(userGroupExportRecordVO.getExportId())) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_FORMAT, "export_id format error");
        }
        // 设置查询参数
        TokenDTO token = SecurityContextHolder.getToken();
        UserGroupExportRecordDTO importRecordDTO = new UserGroupExportRecordDTO();
        importRecordDTO.setOrgId(token.getOrgId());
        importRecordDTO.setCreatorId(token.getUserId());
        importRecordDTO.setExportId(userGroupExportRecordVO.getExportId());
        // 系统管理员与高级管理员不限制查看日志的数据权限
        if ((token.getIsSenior() != null && UserEnum.USER_YES.getFlag().equals(token.getIsSenior()))
                || (token.getSuperRole() != null && UserEnum.USER_YES.getFlag().equals(token.getSuperRole()))) {
            importRecordDTO.setCreatorId(null);
        }
        // 查询导入组织记录
        ServiceResult<List<UserGroupExportRecordDTO>> result = userGroupExportRecordService.findByCondition(importRecordDTO);
        // 设置返回值
        if (result.isSuccess()) {
            if (CollectionUtils.isEmpty(result.getData())) {
                return XmResultJson.fail(ResourceErrorCodeEnum.NOT_FOUND, "export_id not found");
            }
            return XmResultJson.success(userGroupExportRecordConvert.dto2Vo(result.getData().get(0)));
        }

        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 获取指定组在指定层级上的子组织关联的用户数总和
     * python引用：无 新接口
     *
     * @param groupId      组织id
     * @param groupLevelId 層級id
     * @return com.bestcem.xm.util.XmResultJson<com.alibaba.fastjson.JSONObject>
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/06/27 19:06
     */
    @GetMapping({"/userNum", "/user_num"})
    public XmResultJson<JSONObject> getUserNum(@RequestParam("group_id") String groupId,
                                               @RequestParam("group_level_id") String groupLevelId) {
        TokenDTO currentToken = SecurityContextHolder.getToken();
        if (!Pattern.matches(RegTypes.OBJECT_ID, groupId)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_FORMAT, "group_id格式不正确");
        }
        if (!Pattern.matches(RegTypes.OBJECT_ID, groupLevelId)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_FORMAT, "group_level_id格式不正确");
        }
        // 请求用户数量
        ServiceResult<Long> result = userGroupService.getUserNum(groupId, groupLevelId, currentToken.getOrgId(), currentToken.getUserId());
        if (result.isSuccess() && Objects.nonNull(result.getData())) {
            JSONObject json = new JSONObject();
            json.put("user_num", result.getData());
            return XmResultJson.success(json);
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }


    /**
     * 批量删除失效节点
     *
     * @param groupIdList
     * @return com.bestcem.xm.util.XmResultJson<java.lang.Integer>
     * @author Linzhijian <zhijian.lin@idiaoyan.com>
     * @date 2022/08/03 16:02
     */
    @DeleteMapping("/invalid/delete/")
    public XmResultJson<Integer> deleteInvalidGroup(@RequestParam("group_id_list") List<String> groupIdList) {
        if (CollectionUtils.isEmpty(groupIdList)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_LOST, "组织id不允许为空");
        }
        String userId = SecurityContextHolder.getToken().getUserId();
        ServiceResult<Integer> result = userGroupService.deleteInvalidGroup(userId, groupIdList);
        if (result.isSuccess()) {
            return XmResultJson.success(result.getData());
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 获取成员组
     * 当url指定id时，直接查询该id的成员组，忽略其他筛选参数
     * 当url没有指定id时，返回分页查询结果，参数在query中
     */
    @GetMapping("/")
    public XmResultJson group(@RequestParam(required = false, defaultValue = "0") Integer onlyValidate,
                              @RequestParam(required = false) Integer page,
                              @RequestParam(required = false) Integer rowsPerPage,
                              @RequestParam(required = false) Integer status,
                              @RequestParam(required = false) String search) {
        return XmResultJson.handleServiceResult(userGroupService.userGroup(BooleanUtils.toBoolean(onlyValidate), page, rowsPerPage, status, search));
    }

    /**
     * 判断指定层级是否有正式答卷提交
     */
    @GetMapping("/{id:[a-fA-F0-9]{24}}/code-editable")
    public XmResultJson<Boolean> groupCodeEditable(@PathVariable(value = "id") String id) {
        return XmResultJson.success(!userGroupService.groupCodeEditable(id));
    }

    /**
     * 层级编辑-账号管理
     * 用户和组的关联
     * 在一个组织结构（相同根组）中,一个用户只能属于一个组
     */
    @GetMapping("/{id:[a-fA-F0-9]{24}}/users/")
    public XmResultJson<?> groupUser(@PathVariable(value = "id") String id,
                                     @RequestParam(required = false) Integer page,
                                     @RequestParam(required = false) Integer rowsPerPage,
                                     @RequestParam(required = false) Integer returnCount) {
        return XmResultJson.handleServiceResult(userGroupService.groupUser(id, page, rowsPerPage, returnCount));
    }

    /**
     * 层级编辑-编码检查
     */
    @GetMapping("/{id:[a-fA-F0-9]{24}}/code-check")
    public XmResultJson<Boolean> groupCodeCheck(@PathVariable(value = "id") String id,
                                                @RequestParam(required = false) String code) {
        return XmResultJson.success(userGroupService.groupCodeCheck(id, code));
    }

    /**
     * 下载层级结构模板
     */
    @GetMapping("/template")
    public void groupTemplate(HttpServletResponse response) {
        InputStream in = null;
        ServletOutputStream out = null;
        try {
            String templateName = "层级结构模版";
            in = ResourceUtil.getStream("file/excel/levelStructureTemplate.xlsx");
            response.reset();
            response.setContentType("application/x-msdownload");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(templateName + ".xlsx", "utf-8"));
            out = response.getOutputStream();
            IOUtils.copy(in, out);
        } catch (IOException e) {
            log.error("模板下载失败", e);
        } finally {
            IOUtils.closeQuietly(out);
            IOUtils.closeQuietly(in);
        }
    }
}
